﻿using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace zykControl
{
    [DefaultEvent("ValueChanged")]
    public partial class DateSelect
    {
        public DateSelect()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 当任何一个时间选项被改变时发生
        /// </summary>
        /// <remarks></remarks>
        public event ValueChangedEventHandler? ValueChanged;

        public delegate void ValueChangedEventHandler(object? Sender, EventArgs? e);

        private static event StartLimitChangedEventHandler? StartLimitChanged;

        private delegate void StartLimitChangedEventHandler(object? sender, EventArgs? e);

        private static DateTime mStartLimit;
        /// <summary>是否停止触发ValueChange事件</summary>
        private bool mStopRaiseValueChangedEvent;

        /// <summary>
        /// 设置一个时间范围
        /// </summary>
        /// <param name="DateStartEnum"></param>
        /// <param name="DateEnd"></param>
        /// <remarks></remarks>
        public void SetDate(EmDateSelect DateStartEnum, DateTime DateEnd)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.MinDate = mStartLimit;
            dtEnd.MinDate = mStartLimit;
            if (DateEnd < mStartLimit)
                dtEnd.Value = mStartLimit;
            else
                dtEnd.Value = DateEnd;
            var dDate = GetDateFirst(DateStartEnum);
            if (dDate < mStartLimit)
                dtStart.Value = mStartLimit;
            else
                dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        /// <summary>
        /// 设置一个时间范围
        /// </summary>
        /// <param name="DateStart"></param>
        /// <param name="DateEnd"></param>
        /// <remarks></remarks>
        public void SetDate(DateTime DateStart, DateTime DateEnd)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.MinDate = mStartLimit;
            dtEnd.MinDate = mStartLimit;
            if (DateStart < mStartLimit)
                dtStart.Value = mStartLimit;
            else
                dtStart.Value = DateStart;
            if (DateEnd < mStartLimit)
                dtEnd.Value = mStartLimit;
            else
                dtEnd.Value = DateEnd;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        /// <summary>
        /// 设置开始时间为月初/年初/星期日/季度初
        /// </summary>
        /// <param name="DateSelectEnum"></param>
        /// <remarks></remarks>
        public void SetDateStart(EmDateSelect DateSelectEnum)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.MinDate = mStartLimit;
            dtEnd.MinDate = mStartLimit;
            var dDate = GetDateFirst(DateSelectEnum);
            if (dDate < mStartLimit)
                dtStart.Value = mStartLimit;
            else
                dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        /// <summary>
        /// 设置起始时间限制,所有DateSelect控件的最早可选时间都不可能早于这个时间
        /// </summary>
        /// <param name="theDate"></param>
        public static void SetStartLimit(DateTime theDate)
        {
            mStartLimit = theDate;
            StartLimitChanged?.Invoke(null, null);
        }

        /// <summary>
        /// 按指定选择返回最初的一天
        /// </summary>
        /// <param name="DateSelectEnum"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public DateTime GetDateFirst(EmDateSelect DateSelectEnum)
        {
            var dDate = dtEnd.Value;
            switch (DateSelectEnum)
            {
                case EmDateSelect.Month:
                    {
                        return new DateTime(dDate.Year, dDate.Month, 1);
                    }
                case EmDateSelect.Season:
                    {
                        int dMonth;
                        if (dDate.Month > 10)
                        {
                            dMonth = 10;
                        }
                        else if (dDate.Month > 7)
                        {
                            dMonth = 7;
                        }
                        else if (dDate.Month > 4)
                        {
                            dMonth = 4;
                        }
                        else
                        {
                            dMonth = 1;
                        }

                        return new DateTime(dDate.Year, dMonth, 1);
                    }
                case EmDateSelect.Week:
                    {
                        return dDate.AddDays(-(int)dDate.DayOfWeek);
                    }
                case EmDateSelect.Year:
                    {
                        return new DateTime(dDate.Year, 1, 1);
                    }
                default:
                    {
                        return dDate;
                    }
            }
        }

        /// <summary>
        /// 开始时间
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public DateTime StartDate
        {
            get
            {
                return dtStart.Value;
            }

            set
            {
                mStopRaiseValueChangedEvent = true;
                if (value < mStartLimit)
                    dtStart.Value = mStartLimit;
                else
                    dtStart.Value = value;
                mStopRaiseValueChangedEvent = false;
                ValueChanged?.Invoke(this, new EventArgs());
            }
        }

        /// <summary>
        /// 结束时间
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        public DateTime EndDate
        {
            get
            {
                return dtEnd.Value;
            }

            set
            {
                mStopRaiseValueChangedEvent = true;
                if (value < mStartLimit)
                    dtEnd.Value = mStartLimit;
                else
                    dtEnd.Value = value;
                mStopRaiseValueChangedEvent = false;
                ValueChanged?.Invoke(this, new EventArgs());
            }
        }

        private void LinkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ContextMenuStrip1.Show(MousePosition);
        }

        private void 本日ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDateStart(EmDateSelect.Day);
        }

        private void 月初ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDateStart(EmDateSelect.Month);
        }

        private void 年初ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDateStart(EmDateSelect.Year);
        }

        private void 星期日ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDateStart(EmDateSelect.Week);
        }

        private void 本季度ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SetDateStart(EmDateSelect.Season);
        }

        private void DateTimePicker1_ValueChanged(object sender, EventArgs e)
        {
            if (Created == false) return;
            if (FindForm()!.Created == false) return;
            if (mStopRaiseValueChangedEvent == false) ValueChanged?.Invoke(this, new EventArgs());
        }

        private void DateTimePicker2_ValueChanged(object sender, EventArgs e)
        {
            if (Created == false) return;
            if (mStopRaiseValueChangedEvent == false) ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 上一天ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (dtStart.Value.AddDays(-1) >= mStartLimit)
            {
                mStopRaiseValueChangedEvent = true;
                dtStart.Value = dtStart.Value.AddDays(-1);
                mStopRaiseValueChangedEvent = false;
                ValueChanged?.Invoke(this, new EventArgs());
            }
        }

        private void 下一天ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddDays(1d);
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 上一月ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dDate = dtStart.Value.AddMonths(-1);
            if (dDate < mStartLimit) dDate = mStartLimit;
            if (dDate == dtStart.Value) return;
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 上一年ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dDate = dtStart.Value.AddYears(-1);
            if (dDate < mStartLimit) dDate = mStartLimit;
            if (dDate == dtStart.Value) return;
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 上星期ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dDate = dtStart.Value.AddDays(-7);
            if (dDate < mStartLimit) dDate = mStartLimit;
            if (dDate == dtStart.Value) return;
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 上季度ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dDate = dtStart.Value.AddMonths(-3);
            if (dDate < mStartLimit) dDate = mStartLimit;
            if (dDate == dtStart.Value) return;
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 下ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddMonths(3);
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 下星期ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddDays(7d);
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 下一年ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddYears(1);
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 下一月ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddMonths(1);
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 星期一ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dDate = dtEnd.Value;
            int dIndex = (int)dDate.DayOfWeek;
            if (dIndex == 0) dIndex = 7;
            dDate = dDate.AddDays(-dIndex + 1);
            if (dDate < mStartLimit) dDate = mStartLimit;
            if (dDate == dtStart.Value) return;

            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        private void 七天前ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var dDate = dtEnd.Value.AddDays(-7);
            if (dDate < mStartLimit) dDate = mStartLimit;
            if (dDate == dtStart.Value) return;

            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dDate;
            mStopRaiseValueChangedEvent = false;
            ValueChanged?.Invoke(this, new EventArgs());
        }

        // Private Sub DateSelect_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        // Width = dtEnd.Left + dtEnd.Width
        // Height = dtEnd.Height
        // End Sub

        private void LlbTo_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ContextMenuStrip2.Show(MousePosition);
        }

        private void 上移一日ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            var dDate = dtEnd.Value.AddDays(-1);
            if (dDate < mStartLimit) return;
            dtEnd.Value = dDate;
            dDate = dtStart.Value.AddDays(-1);
            if (dDate < mStartLimit) return;
            mStopRaiseValueChangedEvent = false;
            dtStart.Value = dDate;
        }

        private void 上移一星期ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            var dDate = dtEnd.Value.AddDays(-7);
            if (dDate < mStartLimit) dDate = mStartLimit;
            dtEnd.Value = dDate;
            dDate = dtStart.Value.AddDays(-7);
            if (dDate < mStartLimit) dDate = mStartLimit;
            mStopRaiseValueChangedEvent = false;
            dtStart.Value = dDate;
        }

        private void 上移一月ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            var dDate = dtEnd.Value.AddMonths(-1);
            if (dDate < mStartLimit) dDate = mStartLimit;
            dtEnd.Value = dDate;
            dDate = dtStart.Value.AddMonths(-1);
            if (dDate < mStartLimit) dDate = mStartLimit;
            mStopRaiseValueChangedEvent = false;
            dtStart.Value = dDate;
        }

        private void 上移一年ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            var dDate = dtEnd.Value.AddYears(-1);
            if (dDate < mStartLimit) dDate = mStartLimit;
            dtEnd.Value = dDate;
            dDate = dtStart.Value.AddYears(-1);
            if (dDate < mStartLimit) dDate = mStartLimit;
            mStopRaiseValueChangedEvent = false;
            dtStart.Value = dDate;
        }

        private void 上移一季度ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            var dDate = dtEnd.Value.AddMonths(-3);
            if (dDate < mStartLimit) dDate = mStartLimit;
            dtEnd.Value = dDate;
            dDate = dtStart.Value.AddMonths(-3);
            if (dDate < mStartLimit) dDate = mStartLimit;
            mStopRaiseValueChangedEvent = false;
            dtStart.Value = dDate;
        }

        private void 下移一日ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddDays(1d);
            mStopRaiseValueChangedEvent = false;
            dtEnd.Value = dtEnd.Value.AddDays(1d);
        }

        private void 下移一星期ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddDays(7d);
            mStopRaiseValueChangedEvent = false;
            dtEnd.Value = dtEnd.Value.AddDays(7d);
        }

        private void 下移一月ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddMonths(1);
            mStopRaiseValueChangedEvent = false;
            dtEnd.Value = dtEnd.Value.AddMonths(1);
        }

        private void 下移一年ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddYears(1);
            mStopRaiseValueChangedEvent = false;
            dtEnd.Value = dtEnd.Value.AddYears(1);
        }

        private void 下移一季度ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            mStopRaiseValueChangedEvent = true;
            dtStart.Value = dtStart.Value.AddMonths(3);
            mStopRaiseValueChangedEvent = false;
            dtEnd.Value = dtEnd.Value.AddMonths(3);
        }

        private void DtStart_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r') e.Handled = true;
        }

        private void DtStart_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter) dtEnd.Focus();
        }

        private void DtEnd_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode != Keys.Enter) return;

            var dForm = FindForm();
            if (dForm is null) return;

            SendKeys.Send("\t");
        }

        private void LinkLabel1_Enter(object sender, EventArgs e)
        {
            dtStart.Focus();
        }

        private void DateSelect_StartLimitChanged(object sender, EventArgs e)
        {
            if (dtStart.Value < mStartLimit) dtStart.Value = mStartLimit;
            dtStart.MinDate = mStartLimit;
            if (dtEnd.Value < mStartLimit) dtEnd.Value = mStartLimit;
            dtEnd.MinDate = mStartLimit;
        }
    }

    /// <summary>用于双日期选择框的开始时间的快捷调整</summary>
    public enum EmDateSelect
    {
        /// <summary>日</summary>
        Day,
        /// <summary>年</summary>
        Year,
        /// <summary>月</summary>
        Month,
        /// <summary>星期</summary>
        Week,
        /// <summary>季</summary>
        Season
    }
}